#include "BbsControlData.h"
#include "Subs.h"
#include "Input.h"
#include "StringTable.h"
#include "Session.h"
#include "Users.h"
#include "Edit.h"
#include "OverlayManagement.h"
#include "UserPortRS232.h"

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <device.h>
#include <unistd.h>
#include <errno.h>
#include <cbm.h>
#include <time.h>
#include <ctype.h>

#pragma code-name("NEWCODE");
#pragma rodata-name("NEWCODE");
#pragma data-name("NEWDATA");
#pragma bss-name("NEWBSS");

#define FILEPATTERN_SUBBOARD		"sub-%05u"
#define FILEPATTERN_THREAD			"thrd-%04X-%04X"
#define FILEPATTERN_MSG_IDX_REC		"idx-%04X%04X%04X"
#define FILEPATTERN_MSG				"msg-%04X%04X%04X"
#define FILEPATTERN_MSG_BODY		"bdy-%04X%04X%04X"

unsigned int getUnreadCount(void);
unsigned int getUnreadMessageCount(void);

void loadCurrents(void);


char buffer[81];

void loadThreadNew(int threadNumber, bool loadIndexRecord)
{
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];

	file = NULL;

	if(threadNumber == _currentMsgThread.threadNumber) return;
	if(threadNumber < 1) return;
	if(threadNumber > _currentSubboard.highThreadNumber) return;
	
	memset(&_currentMsg, 0, sizeof(message_t));

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);

	sprintf(filename, FILEPATTERN_THREAD, _currentSubboard.subboardNumber, threadNumber);
	file = fopen(filename, "rb");

	memset(&_currentMsgThread, 0, sizeof(msgThread_t));

	if(file != NULL)
	{
		if(fread(&_currentMsgThread, sizeof(msgThread_t), 1, file) == 1)
		//{
		//	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CRLF CHX_RED "Could not read thread." CRLF);
		//}
		//else 
		{
			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_ENTERED_THREAD_1);
			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), _currentMsgThread.topic);
			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_ENTERED_THREAD_2);
			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), _currentMsgThread.startedByAlias);

			if(loadIndexRecord)
			{
				fclose(file);
				memset(&_currentUserMsgIdx, 0, sizeof(userMsgIdxRec_t));
			
				sprintf(filename, FILEPATTERN_MSG_IDX_REC, _currentSubboard.subboardNumber, threadNumber, _currentUser.usernumber);
				file = fopen(filename, "rb");
				if(file != NULL &&
					fread(&_currentUserMsgIdx, sizeof(userMsgIdxRec_t), 1, file) != 1)
				{
					fclose(file);

					//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CRLF CHX_BROWN "Failed to read user msg idx record. ");
					//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), itoa(_currentUserMsgIdx.lastMessageNumber, filename, 10));

					_currentUserMsgIdx.subboardNumber = _currentSubboard.subboardNumber;
					_currentUserMsgIdx.threadNumber = threadNumber;
					_currentUserMsgIdx.lastMessageNumber = 0;

					file = fopen(filename, "wb");
					if(file != NULL &&
						fwrite(&_currentUserMsgIdx, sizeof(userMsgIdxRec_t), 1, file) != 1)
					{
						//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), "Could not write index record.");
					}
					fclose(file);

					_currentSession.lastMessageNumber = _currentUserMsgIdx.lastMessageNumber;
				}
				else if (file == NULL)
				{
					//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CRLF CHX_RED "Could not read user msg index record." CRLF);
					_currentUserMsgIdx.subboardNumber = _currentSubboard.subboardNumber;
					_currentUserMsgIdx.threadNumber = threadNumber;
					_currentUserMsgIdx.lastMessageNumber = 0; // _currentUserMsgIdx.lastMessageNumber;
				}
				fclose(file);

				_currentSession.lastMessageNumber = _currentUserMsgIdx.lastMessageNumber;
				_currentSession.lastThreadNumber = threadNumber;
			}
		}
	}
	//else
	//{
	//	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CRLF CHX_RED "Could not open thread [");
	//	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), itoa(_errno, filename, 10));
	//	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), "]" CRLF);	
	//}

	fclose(file);
	chdir(oldDirectory);
}

void readMessage(int subboardId, unsigned int threadId, unsigned int messageId)
{
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];
	static char timebuffer[31];
	//static char buffer[81];
	static user_t tempUser;
	static msgStatus_t msgStatus;
	static int c;

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);

	sprintf(filename, FILEPATTERN_MSG, subboardId, threadId, messageId);

	file = fopen(filename, "rb");
	if(file != NULL)
	{
		if(fread(&_currentMsg, sizeof(message_t), 1, file))
		{
			if(fread(&msgStatus, sizeof(msgStatus_t), 1, file) != 1)
			{
				msgStatus.lastUpdatedBy = _currentMsg.postedByUsernumber;
				msgStatus.lastUpdatedOn = _currentMsg.postedOn;
				msgStatus.status = MS_NORMAL;
			}

			//fclose(file);

			_currentSession.lastMessageNumber = messageId;

			if(msgStatus.status == MS_NORMAL)
			{
				memset(timebuffer, 0, 31);
				strftime(timebuffer, 31, "%I:%M:%S %p %m/%d/%Y", localtime(&(_currentMsg.postedOn)));
				if(_currentMsg.responseToMessageNumber > 0)
				{
					loadUserByNumber(_currentMsg.respondingToUsernumber, &tempUser);
				}
				outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_MSG_HEADER_1);
				loadUserByNumber(_currentMsg.postedByUsernumber, &tempUser);
				sprintf(buffer, SUBS_MSG_HEADER_2, tempUser.decorated_username);
				outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), buffer);
				sprintf(buffer, SUBS_MSG_HEADER_3, timebuffer);
				outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), buffer);
				sprintf(buffer, SUBS_MSG_HEADER_4, _currentMsg.subject);
				outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), buffer);
				//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_MSG_HEADER_5);
				if(_currentMsg.responseToMessageNumber > 0)
				{
					sprintf(buffer, SUBS_MSG_HEADER_6, tempUser.decorated_username);
					outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), buffer);
					sprintf(buffer, SUBS_MSG_HEADER_7, _currentMsg.responseToMessageNumber);
					outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), buffer);
				}
				outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_MSG_HEADER_8);
				outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CRLF);

				fclose(file);

				sprintf(filename, FILEPATTERN_MSG, subboardId, threadId, messageId);
				file = fopen(filename, "rb");
				memset(buffer, 0, 11);
				if(file != NULL
					&& fread(&_currentMsg, sizeof(message_t), 1, file)
					&& fread(&msgStatus, sizeof(msgStatus_t), 1, file))
				{
					while((c = fread(buffer, 1, 10, file)) > 0)
					{
						outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), buffer);
						memset(buffer, 0, 11);
					}
				}
				fclose(file);

				sprintf(filename, FILEPATTERN_MSG_IDX_REC, subboardId, threadId, _currentUser.usernumber);
				_currentUserMsgIdx.subboardNumber = subboardId;
				_currentUserMsgIdx.threadNumber = threadId;
				_currentUserMsgIdx.lastMessageNumber = messageId;
				_currentSession.lastMessageNumber = messageId;
				file = fopen(filename, "wb");
				if(file != NULL)
				{
					if(fwrite(&_currentUserMsgIdx, sizeof(userMsgIdxRec_t), 1, file))
					{
					}
				}
				fclose(file);
			}
			else
			{
				sprintf(buffer, SUBS_READ_MSG_DELETED, messageId);
				outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), buffer);

				_currentUserMsgIdx.subboardNumber = subboardId;
				_currentUserMsgIdx.threadNumber = threadId;
				_currentUserMsgIdx.lastMessageNumber = messageId;
				_currentSession.lastMessageNumber = messageId;
			}
		}
		else
		{
			fclose(file);
		}
	}

	fclose(file);
	chdir(oldDirectory);
}

void saveCurrentThread(void)
{
	char threadTopic[71];
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);

	sprintf(filename, FILEPATTERN_THREAD, _currentSubboard.subboardNumber, _currentMsgThread.threadNumber);
	file = fopen(filename, "wb");

	if(file != NULL && 
		fwrite(&_currentMsgThread, sizeof(msgThread_t), 1, file) != 1)
	{
		//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CHX_RED "Could not write thread." CRLF);
	}

	fclose(file);

	chdir(oldDirectory);
}

void createMessage(bool reply)
{
	static char buffer[81];
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];
	static int originalPoster;
	static int originalMessageNumber;

	originalPoster = _currentMsg.postedByUsernumber;
	originalMessageNumber = _currentMsg.messageNumber;

	if(_currentMsgThread.threadNumber == 0)
	{
		outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_NO_THREAD);
		return;
	}

	memset(&_currentMsg, 0, sizeof(message_t));
	memset(&_editInfo, 0, sizeof(editInfo_t));

	_currentMsg.messageNumber = _currentMsgThread.highMessageNumber + 1;
	_currentMsg.postedOn = _systime() + _baseTime;
	_currentMsg.postedByUsernumber = _currentUser.usernumber;

	if(reply)
	{
		_currentMsg.respondingToUsernumber = originalPoster;
		_currentMsg.responseToMessageNumber = originalMessageNumber;
	}

	if(_currentSubboard.subboardNumber == 0)
	{
		_currentMsg.isPrivate = true;
	}

	_currentMsg.originalEncoding = PLATFORM_ENCODING;

	sprintf(_editInfo.filename, FILEPATTERN_MSG_BODY, _currentSubboard.subboardNumber, _currentMsgThread.threadNumber, _currentMsg.messageNumber);
	_editInfo.message = &_currentMsg;

	//pause(PLATFORM_ENCODING, OD_SCREEN);

	loadOverlay("bbs.edit", &enterEditor, "bbs.new");


}

void loadSubboard(int subboardNumber)
{
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];

	if(subboardNumber < 0 )
	{
		return;
	}

	_currentSession.lastSubboard = subboardNumber;

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);
		
	sprintf(filename, FILEPATTERN_SUBBOARD, subboardNumber);
	file = fopen(filename, "rb");
	if(file != NULL)
	{
		if(fread(&_currentSubboard, sizeof(subboard_t), 1, file))
		{
			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_ENTER_SUBBOARD);
			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), _currentSubboard.description);

			memset(&_currentMsgThread, 0, sizeof(msgThread_t));
			if(_currentSubboard.lowThreadNumber > 0)
			{
				loadThreadNew(_currentSubboard.lowThreadNumber, true);
			}
			else
			{
				_currentSession.lastMessageNumber = 0;
				_currentSession.lastThreadNumber = 0;
			}
		}
	}

	fclose(file);
	chdir(oldDirectory);
}

void readMessageByNumber(void)
{
	static char temp[5];
	static int messageId;

	messageId = 0;
	memset(temp, 0, 5);

	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_READ_MSG);
	input(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), IO_NUMERIC, temp, 4, false);

	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF);

	messageId = atoi(temp);

	if(messageId > 0 && messageId <= _currentMsgThread.highMessageNumber)
	{
		readMessage(_currentSubboard.subboardNumber, _currentMsgThread.threadNumber, messageId);
	}
}

void newMessageScan(void)
{
	bool originalDCD = readDCD();
	static char originalSubboard;
	static int originalThread;
	static int i, j, k;
	static char c;

	static subIndexRec_t current;
	static bases_t localbases;

	static subIndexRec_t subs[20];
	
	static FILE *file;
	static char oldDirectory[17];
	static char directory[17];
	static char filename[17];

	getcwd(oldDirectory, 17);
	getdevicedir(bcd.dataDirectory.device, directory, 17);
	chdir(directory);
		
	file = fopen("subsindex", "rb");
	
	if(file != NULL)
	{
		if(fread(&localbases, sizeof(bases_t), 1, file))
		{
			for(i = 0; i<localbases.subboardCount; ++i)
			{
				if(fread(&current, sizeof(subIndexRec_t), 1, file))
				{
					memcpy(&subs[i], &current, sizeof(subIndexRec_t));
				}
				//else
				//{
				//	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CHX_RED "Could not open subboard record.");
				//}
			}
		}
		//else
		//{
		//	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CHX_RED "Could not read subsindex bases record.");
		//}

		fclose(file);

		for(i = 0; i<localbases.subboardCount; ++i)
		{
			memcpy(&current, &subs[i], sizeof(subIndexRec_t));

			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_NEW_MSGS_SUBBOARD);
			outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), current.name);

			memset(&_currentMsgThread, 0, sizeof(msgThread_t));

			loadSubboard(current.subboardNumber);

			if(_currentSubboard.highThreadNumber > 0)
			{
				for(j = _currentSubboard.lowThreadNumber;
					j <= _currentSubboard.highThreadNumber;
					++j)
				{
					loadThreadNew(j, true);

					//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_NEW_MSGS_THREAD);
					//outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), _currentMsgThread.topic);

					for(k = _currentUserMsgIdx.lastMessageNumber + 1;
						k <= _currentMsgThread.highMessageNumber;
						++k)
					{
						readMessage(current.subboardNumber, j, k);

						outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), SUBS_READ_MSG_PROMPT);

						while((c = tolower(inputChar(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), IO_ALPHA))) != 'q'
							&& c != 'r' && c != 'n')
						{
							if(readDCD() != originalDCD) return;
						}

						outputCharacter(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), c);
						switch(c)
						{
						case 'q': 
							fclose(file);
							chdir(oldDirectory);

							loadSubboard(originalSubboard);
							loadThreadNew(originalThread, true);
							return;
						case 'r':
							reply();
							break;

						}
					}
				}
			}
		}
	}
	//else
	//{
	//	outputString(PLATFORM_ENCODING, (outDirections_t)(OD_MODEM | OD_SCREEN), CRLF CHX_RED "Could not open subsindex.");
	//}

	chdir(oldDirectory);

	loadSubboard(originalSubboard);
	loadThreadNew(originalThread, true);
}

void reply(void)
{
	createMessage(true);
}